﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace FSM
{
    public abstract class FSMMachineBase
    {
        private Dictionary<int, FSMState> m_stateMap;

        private FSMState m_defaultState;
        private FSMState m_currentState;
        public FSMState CurrentState
        {
            get
            {
                return m_currentState;
            }
        }
        private FSMState m_goalState;
        private int m_goalID;

        private bool m_changeByOutSide = false;
        private int m_changeType;
        private int m_lazy = 0;

        public FSMController controller;

        public FSMMachineBase(FSMController parent)
        {
            controller = parent;
            m_stateMap = new Dictionary<int, FSMState>();
            LoadStates();
        }

        protected abstract void LoadStates();

        public virtual void UpdateMachine(int t)
        {
            if (m_stateMap.Count == 0)
            {
                return;
            }
            if (m_currentState == null) // 自动机启动后第一次执行
            {
                if (m_defaultState != null)
                {
                    m_currentState = m_defaultState;
                    m_currentState.Enter();
                }
                else
                {
                    return;
                }
            }

            var oldStateID = m_currentState.type;

            m_goalID = m_currentState.CheckTransitions(0);

            if (m_changeByOutSide)
            {
                if (m_goalID != m_changeType)
                {
                    m_goalID = m_changeType;
                }
                else
                {
                    m_changeType = 0;
                    m_changeByOutSide = false;
                }
            }

            if (m_goalID != oldStateID)
            {
                if (CanTransitionState(m_goalID) && m_lazy > m_stateMap[m_goalID].lazyTime) // 处理震荡
                {
                    m_goalState = m_stateMap[m_goalID];
                    m_currentState.Exit();
                    m_currentState = m_goalState;
                    m_currentState.Enter();
                    m_lazy = 0;
                }
            }
            m_currentState.Update();
            m_lazy += 1;
        }

        public void AddState(FSMState state)
        {
            m_stateMap.Add(state.type, state);
        }

        public void ChangeState(int type)
        {
            m_changeType = type;
            m_changeByOutSide = true;
        }

        public void SetDefaultState(FSMState state)
        {
            m_defaultState = state;
        }

        public void SetGoalID(int state)
        {
            m_goalID = state;
        }

        public bool CanTransitionState(int goal)
        {
            return m_stateMap.ContainsKey(goal);
        }

        public virtual void Reset() { }
    }
}